lexer grammar Language;
@members {
    class SaveStruct {
      SaveStruct(CharStream input){
        this.input = input;
        this.marker = input.mark();
      }
      public CharStream input;
      public int marker;
      public File basePath;
     }
     
     File basePath = new File(".");
     public void setBasePath(String path){
     	basePath = new File(path);
     }
     

     Stack<SaveStruct> includes = new Stack<SaveStruct>();

    // We should override this method for handling EOF of included file
     public Token nextToken(){
       Token token = super.nextToken();

       if(token==Token.EOF_TOKEN && !includes.empty()){
        // We've got EOF and have non empty stack.
         SaveStruct ss = includes.pop();
         basePath = ss.basePath;
         setCharStream(ss.input);
         input.rewind(ss.marker);
         token = super.nextToken();
       }

      // Skip first token after switching on another input.
      // You need to use this rather than super as there may be nested include files
       if(((CommonToken)token).getStartIndex() < 0)
         token = this.nextToken();

       return token;
     }
 }
@header {
package ac.jp.u_tokyo.SyncLib.language3;
import java.io.File;
}

CONST : 'const_value' ;
TRUE : 'true' ;
FALSE : 'false' ;
NULL : 'null' ;
FOR : 'for' ;
IN : 'in' ;
VAR : 'var' ;
T22 : '<' ;
T23 : ',' ;
T24 : '>' ;
T25 : '=' ;
T26 : '(' ;
T27 : ')' ;
T28 : '{' ;
T29 : ';' ;
T30 : '|' ;
T31 : '}' ;
T32 : '.' ;
T33 : '!' ;
T34 : '==' ;
T35 : '<>' ;
T36 : '[' ;
T37 : ']' ;

// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 100
fragment DIGIT 
	:	'0'..'9';
	
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 103
fragment ULETTER
	:	'A'..'Z';
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 105
fragment LLETTER
	:	'a'..'z';
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 107
fragment LETTER
	:	ULETTER | LLETTER | '_';	

// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 110
NUMBER : DIGIT+;
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 111
NAME 	:	LETTER (DIGIT | LETTER)*;
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 112
STRING : ('\"' | '\'') (~('\"' | '\''))* ('\"' | '\'');


// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 115
COMMENT			
		:	'/*'  ( options {greedy=false;}:.)* '*/' 			  {skip();}
		|	'/' '\\' '\n' '*'  ( options {greedy=false;}:.)* '*/' {skip();}
		;
// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 119
LINE_COMMENT :	'//'(~('\n' | '\r')*)('\n' | '\r') {skip();};

// $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 121
WS
    : (' '| '\t' | '\n' | '\r')+ {skip();};
    
 // $ANTLR src "C:\Documents and Settings\t2ladmin\My Documents\Projects\2008\OS3\SyncLib\src\ac\jp\u_tokyo\SyncLib\language3\Language.g" 124
INCLUDE
     : 'include' (WS)? f=STRING {
       String name = f.getText();
       name = name.substring(1,name.length()-1);
       try {
        // save current lexer's state
         SaveStruct ss = new SaveStruct(input);
         ss.basePath = basePath;
         includes.push(ss);
         
         name = basePath.getAbsolutePath() + File.separator + name;
         basePath = new File(name).getAbsoluteFile().getParentFile();

        // switch on new input stream
         setCharStream(new ANTLRFileStream(name));
         reset();

       } catch(Exception fnf) { throw new Error("Cannot open file " + name); }
     }
     ;
    
  
      

